package cn.thornbird.orgsync.controller;

import cn.thornbird.orgsync.annotation.CurrentUser;
import cn.thornbird.orgsync.entity.Attachment;
import cn.thornbird.orgsync.entity.User;
import cn.thornbird.orgsync.entity.status.VerificationCodeUsage;
import cn.thornbird.orgsync.exception.BadRequestException;
import cn.thornbird.orgsync.exception.InternalServerErrorException;
import cn.thornbird.orgsync.model.Result;
import cn.thornbird.orgsync.model.UserData;
import cn.thornbird.orgsync.service.AttachmentService;
import cn.thornbird.orgsync.service.UserService;
import cn.thornbird.orgsync.util.SecurityUtil;
import cn.thornbird.orgsync.vo.request.CheckVerificationCodeRequest;
import cn.thornbird.orgsync.vo.request.SendVerificationCodeRequest;
import com.anji.captcha.controller.CaptchaController;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping(value = "/api")
@Api
@AllArgsConstructor
@Slf4j
public class ApiController {

    private final AttachmentService attachmentService;

    private final UserService userService;

    private final CaptchaService captchaService;

    @GetMapping("ping")
    public Result<String> ping() {
        return Result.success("pong");
    }

    @GetMapping("currentUser")
    public Result<UserData> currentUser(@CurrentUser @ApiIgnore UserData userData) {
        if (!SecurityUtil.isAuthenticated()) {
            return Result.success(null);
        }
        List<User> list = new ArrayList<>();
        UserData currentUser = userService.currentUser(userData, list);
        if (!currentUser.equals(userData) && !list.isEmpty()) {
            SecurityUtil.updateAuthentication(list.get(0));
        }
        return Result.success(currentUser);
    }

    @PostMapping("sendVerificationCode")
    public Result<String> sendVerificationCode(@RequestBody @Valid SendVerificationCodeRequest request) {
        VerificationCodeUsage usage = request.getUsage();
        String mobile = request.getMobile();
        String username = request.getUsername();
        String captchaVerification = request.getCaptchaVerification();
        User user;
        CaptchaVO captchaVO = new CaptchaVO();
        captchaVO.setCaptchaVerification(captchaVerification);
        ResponseModel response = captchaService.verification(captchaVO);
        if (!response.isSuccess()) {
            return Result.error(HttpStatus.BAD_REQUEST.value(), response.getRepMsg());
        }
        if (usage.equals(VerificationCodeUsage.SignUp)) {
            if (StringUtils.isEmpty(mobile)) {
                return Result.error(HttpStatus.BAD_REQUEST.value(), "手机号码不能为空");
            }
            if (!mobile.matches(SendVerificationCodeRequest.MOBILE_REG_EXP)) {
                return Result.error(HttpStatus.BAD_REQUEST.value(), "手机号码不正确");
            }
            user = userService.findByMobile(mobile);
            if (user != null) {
                return Result.error(HttpStatus.BAD_REQUEST.value(), "手机号码已被使用");
            }
        } else if (usage.equals(VerificationCodeUsage.ResetPassword)) {
            if (StringUtils.isEmpty(username)) {
                return Result.error(HttpStatus.BAD_REQUEST.value(), "用户名不能为空");
            }
            user = userService.findByMobileOrUsername(username);
            if (user == null) {
                return Result.error(HttpStatus.BAD_REQUEST.value(), "用户不存在");
            } else if (StringUtils.isEmpty(user.getMobile())) {
                return Result.error(HttpStatus.BAD_REQUEST.value(), "用户未设置手机号码");
            }
            mobile = user.getMobile();
        }
        Boolean success = userService.sendVerificationCode(mobile, usage);
        if (!success) {
            return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "验证码发送失败");
        }
        return Result.success(mobile.substring(0, 3) + "******" + mobile.substring(9, 11));
    }

    @PostMapping("checkVerificationCode")
    public Result<String> checkVerificationCode(@RequestBody @Valid CheckVerificationCodeRequest request) {
        String username = request.getUsername();
        if (StringUtils.isEmpty(username)) {
            return Result.error(HttpStatus.BAD_REQUEST.value(), "用户名不能为空");
        }
        User user = userService.findByMobileOrUsername(username);
        if (user == null) {
            return Result.error(HttpStatus.BAD_REQUEST.value(), "用户不存在");
        } else if (StringUtils.isEmpty(user.getMobile())) {
            return Result.error(HttpStatus.BAD_REQUEST.value(), "用户未设置手机号码");
        }
        String id = userService.findVerificationCode(user.getMobile(), request.getVerificationCode(),
                request.getUsage());
        if (id == null) {
            return Result.error(HttpStatus.BAD_REQUEST.value(), "验证码不正确");
        }
        return Result.success(id);
    }

    @GetMapping("download/{attachmentId}")
    public void download(@PathVariable String attachmentId, HttpServletResponse response) {
        attachmentService.download(attachmentId, response);
    }

    @PostMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Result<Attachment> upload(@RequestPart("file") MultipartFile multipartFile)
            throws BadRequestException, InternalServerErrorException {
        return Result.success(attachmentService.save(multipartFile));
    }

    @PostMapping("getCaptcha")
    public ResponseModel getCaptcha(@RequestBody CaptchaVO data, HttpServletRequest request) {
        assert request.getRemoteHost() != null;
        data.setBrowserInfo(CaptchaController.getRemoteId(request));
        return captchaService.get(data);
    }

    @PostMapping("checkCaptcha")
    public ResponseModel checkCaptcha(@RequestBody CaptchaVO data, HttpServletRequest request) {
        data.setBrowserInfo(CaptchaController.getRemoteId(request));
        return this.captchaService.check(data);
    }

}
